package com.examples;

import android.os.Build;

import androidx.annotation.IntDef;
import androidx.annotation.RequiresApi;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.function.Function;

@RequiresApi(api = Build.VERSION_CODES.N)
public class Dispatcher<T, R> {
    public static final int runOnUiThread = 0;
    public static final int runOnIoThread = 1;

    @Retention(RetentionPolicy.SOURCE)
    @IntDef({runOnUiThread, runOnIoThread})
    public @interface ThreadType {
    }

    private Dispatcher() {
    }

    public static Dispatcher getInstance() {
        return new Dispatcher();
    }

    private DispatcherBean bean;

    public <T, R> Dispatcher deal(@ThreadType int threadType, Function<T, R> function, T t) {
        bean = new DispatcherBean<T, R>(threadType, t, function);
        return this;
    }


    public <T extends R, U> Dispatcher andThen(@ThreadType int threadType, Function<T, U> function) {
        bean = new DispatcherBean<>(threadType, bean, function);
        return this;
    }

    public <R> R build() {
        return (R) compute(bean);
    }

    private  <T, R> R compute(DispatcherBean<T, R> bean) {
        if (bean.beanBean == null) {
            return bean.function.apply(bean.input);
        }
        return (R) compute(bean.beanBean);
    }
}
